package com.kyleromano.disgaea;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import com.kyleromano.disgaea.dataType.CharacterListItemClassComparator;
import com.kyleromano.disgaea.dataType.CharacterListItemDefaultComparator;
import com.kyleromano.disgaea.dataType.CharacterListItemLevelComparator;
import com.kyleromano.disgaea.dataType.CharacterListItemNameComparator;
import com.kyleromano.disgaea.dataType.CharacterListRowItem;
import com.kyleromano.disgaea.sql.CharacterDataSource;
import com.kyleromano.disgaea.sql.DBConstants;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

public class CharacterListViewActivity extends Activity {
	private CharacterDataSource db;
	private Context context;
	@Override
    public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.character_list);
		context = this;
		db = new CharacterDataSource(this);
		db.open();

		// Back to Home Screen
		Button back = (Button)this.findViewById(R.id.characterListViewBackButton);
		back.setOnClickListener(new View.OnClickListener() {
	    	   public void onClick(View view) {
	    		   Intent intent = new Intent();
	    		   setResult(RESULT_OK, intent);
	    		   finish();
	    	   }
	       });
		// New Character
		Button newCharacter = (Button)this.findViewById(R.id.characterListViewNewCharacter);
		newCharacter.setOnClickListener(new View.OnClickListener() {
	    	   public void onClick(View view) {
	    		   Intent detailsIntent = new Intent(view.getContext(), CharacterViewActivity.class);
					detailsIntent.putExtra("id", -1);
					startActivityForResult(detailsIntent,R.layout.character_view_edit);
	    	   }
	       });

		// Change Sort Filters
		Spinner sortBy = (Spinner)this.findViewById(R.id.characterListViewSortBy);
		Switch asc = (Switch)this.findViewById(R.id.characterListViewSortOrder);
		sortBy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        	public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        		Switch asc = (Switch)findViewById(R.id.characterListViewSortOrder);
        		sortList(asc.isChecked(), pos);
        		ContentValues cv = new ContentValues();
        		cv.put(DBConstants.CSORTORDER, pos);
        		db.update(DBConstants.TSYSDATA, cv, DBConstants.CSORTORDER + " < 10", null);
        	}
        	public void onNothingSelected(AdapterView<?> parent){}
        });
		
		// Ascending / Descending order
		asc.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				Spinner sortBy = (Spinner)findViewById(R.id.characterListViewSortBy);
				sortList(isChecked, sortBy.getSelectedItemPosition());
				ContentValues cv = new ContentValues();
				if(isChecked)
					cv.put(DBConstants.CASCENDING, 1);
				else
					cv.put(DBConstants.CASCENDING, 0);
				db.update(DBConstants.TSYSDATA, cv, DBConstants.CASCENDING + " < 10", null);
			}
		});
		
		ListView l = (ListView)findViewById(R.id.characterListViewLayout);
		l.setOnItemClickListener(new OnItemClickListener() {

						public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
							Intent detailsIntent = new Intent(view.getContext(), CharacterViewActivity.class);
    						detailsIntent.putExtra("id", view.getId());
    						startActivityForResult(detailsIntent,R.layout.character_view_edit);
						}
    				});
		setLastSortOrder();
		makeList();
	}
	
	/**
	 * set the switches to their last set sort order
	 */
	private void setLastSortOrder() {
		Spinner sortBy = (Spinner)this.findViewById(R.id.characterListViewSortBy);
		Switch asc = (Switch)this.findViewById(R.id.characterListViewSortOrder);
		Cursor c = db.select("SELECT * FROM " + DBConstants.TSYSDATA, null);
		if(c != null && c.getCount() > 0) {
			if(c.moveToFirst()) {
				sortBy.setSelection(c.getInt(0));
				if(c.getInt(1) == 0)
					asc.setChecked(false);
				else
					asc.setChecked(true);
				c.close();
			}
		}
	}
	
	@Override
	public void onPause()
	{
		super.onPause();
		if(!db.isOpen())
			db.close();
	}
	@Override
	public void onResume()
	{
		super.onResume();
		if(!db.isOpen())
			db.open();
	}
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if(!db.isOpen())
			db.open();
		if(requestCode == R.layout.character_view_edit) {
			if (resultCode == CharacterViewActivity.RESULT_DATA_CHANGED) {
				refreshList(data.getIntExtra("changeId", -1),
						data.getIntExtra("newLevel", 1),
						data.getStringExtra("newName"),
						data.getIntExtra("newJobId", 0),
						data.getIntExtra("newClassId", 0),
						data.getStringExtra("newClassString"));
			} else if (resultCode == CharacterViewActivity.RESULT_CHAR_DELETED) {
				int deletedId = data.getIntExtra("deletedCharacterId", -1);
				String name = data.getStringExtra("deletedCharacterName");
				if(deletedId > 0)
					Toast.makeText(this, String.format(getResources().getString(R.string.sWasRemoved, name)), Toast.LENGTH_SHORT).show();
					this.removeCharacter(deletedId);
			} else if (resultCode == CharacterViewActivity.RESULT_NEW_CHARACTER) {
				insertNewCharacter(data.getIntExtra("changeId", -1),
								data.getIntExtra("newLevel", 1),
								data.getStringExtra("newName"),
								data.getIntExtra("newJobId", 0),
								data.getIntExtra("newClassId", 0),
								data.getStringExtra("newClassString"));
			} else if (resultCode == CharacterViewActivity.RESULT_CHARACTER_NOT_FOUND) {
				Toast.makeText(this, getResources().getString(R.string.sNoRecordFound), Toast.LENGTH_SHORT).show();
			}
		}
	}
	
	/**
	 * Insert a new record into the list adapter
	 */
	private void insertNewCharacter(int changeId, int newLevel, String newName, int newJobId, int newClassId, String newClassString)
	{
		ListView v = (ListView)this.findViewById(R.id.characterListViewLayout);
		CharacterListArrayAdapter adapter = (CharacterListArrayAdapter) v.getAdapter();
		CharacterListRowItem item = new CharacterListRowItem(changeId);
		String desc = "<font color='#FFBA00'>" + newName + "</font><br />" +
				"Lvl: " + newLevel + " " + newClassString;
		item.setDescription(desc);
		try {
			//ClassID - JobID will return an index value between 0 and 5
			int index = newClassId - newJobId;
			Bitmap bmp = ImageFactory.createIcon(getResources().getAssets(), newJobId).getTile(index);
			item.setIcon(bmp);
		} catch (IOException e) {
			e.printStackTrace();
		}
		adapter.add(item);
		v.invalidateViews();
	}
	
	/**
	 * Delete a character from the list because their data was deleted
	 */
	private void removeCharacter(int characterId) {
		ListView v = (ListView)this.findViewById(R.id.characterListViewLayout);
		CharacterListArrayAdapter adapter = (CharacterListArrayAdapter) v.getAdapter();
		CharacterListRowItem item = null;
		for(int x = 0; x < adapter.getCount(); x++) {
			item = adapter.getItem(x);
			if(item.getId() == characterId)
				break;
		}
		if(item != null) {
			adapter.remove(item);
			v.invalidateViews();
		}
	}

	/**
	 * Rebuild the character data list because the data has changed
	 */
	private void refreshList(int changeId, int newLevel, String newName, int newJobId, int newClassId, String newClassString) {
		ListView v = (ListView)this.findViewById(R.id.characterListViewLayout);
		ListAdapter adapter = v.getAdapter();
		CharacterListRowItem item = null;
		for(int position = 0; position < adapter.getCount(); position++) {
			item = (CharacterListRowItem) adapter.getItem(position);
			if(item.getId() == changeId)				
				break;
		}
		if(item != null) {
			String desc = "<font color='#FFBA00'>" + newName + "</font><br />" +
					"Lvl: " + newLevel + " " + newClassString;
			item.setDescription(desc);
			item.setName(newName);
			item.setClassId(newClassId);
			item.setLevel(newLevel);
			try {
				//ClassID - JobID will return an index value between 0 and 5
				int index = newClassId - newJobId;
				Bitmap bmp = ImageFactory.createIcon(getResources().getAssets(), newJobId).getTile(index);
				item.setIcon(bmp);
			} catch (IOException e) {
				e.printStackTrace();
			}
			//v.invalidate();
			v.invalidateViews();
		}
		//makeList();
	}
	
	/**
	 * Sort the list based on the two sort switches
	 */
	private void sortList(boolean ascending, int sortBy) {
    	ListView v = (ListView)this.findViewById(R.id.characterListViewLayout);
		CharacterListArrayAdapter adapter = (CharacterListArrayAdapter) v.getAdapter();
		if(adapter != null && adapter.getCount() > 0){
			if(sortBy == 1) {
				//sort by name
				adapter.sort(new CharacterListItemNameComparator(ascending));
			} else if(sortBy == 2) {
				//sort by level
				adapter.sort(new CharacterListItemLevelComparator(ascending));
			} else if(sortBy == 3) {
				//sort by class
				adapter.sort(new CharacterListItemClassComparator(ascending));
			} else {
				//default sort
				adapter.sort(new CharacterListItemDefaultComparator(ascending));
			}
			v.invalidateViews();
		}
	}
	
	/**
	 * Not the best place for this function call as it may never be called or it may be interrupted before completing
	 * However I really don't have a better place to put it and my current implementation of the database model leaves
	 * much to be desired
	 */
	@Override
	public void onDestroy()
	{
		super.onDestroy();
		db.close();
	}
	
    /**
     * Another piece of picture power
     */
    private void makeList()
    {
    	//AssetManager assets = this.getResources().getAssets();
    	String sort = null;
    	Spinner sortBy = (Spinner)this.findViewById(R.id.characterListViewSortBy);
    	Switch sortOrder = (Switch)this.findViewById(R.id.characterListViewSortOrder);
    	int item = sortBy.getSelectedItemPosition();
    	if(item == 1)
    		sort = DBConstants.CCHARNAME;
    	else if(item == 2)
    		sort = DBConstants.CLEVEL;
    	else if(item == 3)
    		sort = DBConstants.CCLASSID;
    	
    	//Store some data so the inner class can make use of it
    	Object[] o = new Object[] { sort, sortOrder.isChecked() };
    	
    	//Hope to hell that a threaded SQL query won't fail
    	new LoadCharacterListThread(this).execute(o);
    }
    
    
    /**
     * Threaded query for handling the construction of the player data list
     * @author kromano
     *
     */
    private class LoadCharacterListThread extends AsyncTask<Object, Void, ArrayList<CharacterListRowItem>> {
    	private Context context;
    	private ProgressDialog loadingBar;
    	
    	private LoadCharacterListThread(Context context) {
    		this.context = context;
    	}
    	
    	@Override
    	protected ArrayList<CharacterListRowItem> doInBackground(Object... data) {
    		ArrayList<CharacterListRowItem> listItems = null;
    		String sort = (String) data[0];
    		boolean order = (Boolean) data[1];
    		Cursor c = db.getAllCharacters(sort, order);
    		if(c != null)
    		{
    			listItems = new ArrayList<CharacterListRowItem>();
    			AssetManager assets = context.getResources().getAssets();
    			Bitmap bmp;
    			while(c.moveToNext()){

    				//Update the progress spinner if there is one
    				publishProgress();
    				String desc = "<font color='#FFBA00'>" + c.getString(1) + "</font><br />" +
    						"Lvl: " + c.getInt(2) + " " + c.getString(4);
    				try {
    					int jobID = c.getInt(5);
    					int classID = c.getInt(3);
    					//ClassID - JobID will return an index value between 0 and 5
    					int index = classID - jobID;
    					bmp = ImageFactory.createIcon(assets, jobID).getTile(index);
    					//Bitmap bitmap, String description, int id, String name, int level, int classId
    					CharacterListRowItem item = new CharacterListRowItem(bmp, desc, c.getInt(0), c.getString(1), c.getInt(2), classID);
        				listItems.add(item);
        				
    				} catch (IOException e) {
    					e.printStackTrace();
    				}

    			}
    			c.close();
    		}
    		return listItems;
    	}
    	
    	@Override
    	protected void onPreExecute() {
    		String[] loadingStrings = getResources().getStringArray(R.array.aLoadingStrings);
    		// Show a Spinner progressDialog
    		loadingBar = new ProgressDialog(context, ProgressDialog.STYLE_SPINNER);
    		loadingBar.setTitle(loadingStrings[new Random().nextInt(loadingStrings.length)]);
    		loadingBar.show();
    	}
    	
    	@Override
    	protected void onProgressUpdate(Void... v) {
    		
    	}

    	@Override
    	protected void onPostExecute(ArrayList<CharacterListRowItem> listItems) { 
    		ListView v = (ListView)findViewById(R.id.characterListViewLayout);
    		CharacterListArrayAdapter adapter =
    				new CharacterListArrayAdapter(context,android.R.layout.simple_expandable_list_item_1,listItems);
    		v.setAdapter(adapter);
    		loadingBar.dismiss();
    	}
    }
	/**
	 * Inner, class causing me much pain and grief
	 * @author kromano
	 *
	 * @param <T>
	 */
	private class CharacterListArrayAdapter extends ArrayAdapter<CharacterListRowItem> {
		ArrayList<CharacterListRowItem> items;
		public CharacterListArrayAdapter(Context context, int textViewResourceId, ArrayList<CharacterListRowItem> items) {
			super(context, textViewResourceId, items);
			this.items = items;
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			//View v = convertView;
			//if(v == null) {
				//LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				//v = vi.inflate(R.layout.character_list_row, null);
			//}
			TextView t = new TextView(context);
			CharacterListRowItem listItem = items.get(position);
			if(listItem != null) {
				t.setText(Html.fromHtml(listItem.getDescription()));
				t.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(getResources(),listItem.getIcon()), null,null,null);
				t.setCompoundDrawablePadding(10);
				t.setPadding(0, 5, 0, 5);
				t.setId(listItem.getId());
			}
			//return v;
			return t;
		}
	}
}
